/********************************************************
*Implementacion de Lista de listas                      *
*Author     :   Simon Emmanuel Gutierrez Brida          *
*Version    :   0.1                                     *
*Fecha      :   Septiembre/2011                         *
*------------------------------------------------------ *
*********************************************************/

#include <stdlib.h>
#include <stdio.h>
#include "listalistas.h"

ListaListas* nuevaListaListas() {
    ListaListas *nueva = (ListaListas*) malloc(sizeof(ListaListas));
    nueva->inicio = NULL;
    nueva->longitud = 0;
    return nueva;
}

Lista* obtener_listaListas(ListaListas *lista, int index) {
    NodoLista *runner = lista->inicio;
    bool validIndex = (index >= 0) && (index < longitud_listaListas(lista));
    if (validIndex) {
        int i = 0;
        while (i < index) {
            runner = obtenerSiguiente_nodoLista(runner);
            i++;
        }
        return obtenerInfo_nodoLista(runner);
    } 
}

int longitud_listaListas(ListaListas *lista) {
    return lista->longitud;
}

bool existe_listaListas(ListaListas *lista, int index) {
    bool validIndex = (index >= 0) && (index < longitud_listaListas(lista));
    return validIndex && (obtener_listaListas(lista, index) != NULL);
}

void agregar_final_listaListas(ListaListas *lista, Lista *elem) {
    agregar_indexado_listaListas(lista, elem, longitud_listaListas(lista));    
}

void agregar_indexado_listaListas(ListaListas *lista, Lista *elem, int index) {
    bool validIndex = (index >= 0) && (index <= longitud_listaListas(lista));
    if (validIndex) {
        if (index == 0) {
            NodoLista *nuevo = nuevoNodoLista_info_siguiente(elem, lista->inicio);
            lista->inicio = nuevo;
        } else {
            int i = 0;
            NodoLista *runner = lista->inicio;
            while (i < (index - 1)) {
                runner = obtenerSiguiente_nodoLista(runner);
                i++;
            }
            NodoLista *nuevo = nuevoNodoLista_info_siguiente(elem, obtenerSiguiente_nodoLista(runner));
            definirSiguiente_nodoLista(runner, nuevo);
        }
        lista->longitud = longitud_listaListas(lista) + 1;
    }
}

void reescribir_listaListas(ListaListas *lista, Lista *elem, int index) {
    bool validIndex = (index >= 0) && (index <= longitud_listaListas(lista)); 
    if (validIndex) {
        if (index == longitud_listaListas(lista)) {
            agregar_final_listaListas(lista, elem);
        } else {
            int i = 0;
            NodoLista *runner = lista->inicio;
            while (i < index) {
                runner = obtenerSiguiente_nodoLista(runner);
                i++;
            }
            definirInfo_nodoLista(runner, elem);
        }
    }
}

void eliminar_listaListas(ListaListas *lista, int index) {
    bool validIndex = (index >= 0) && (index < longitud_listaListas(lista));
    if (validIndex) {
        NodoLista *runner = lista->inicio;
        NodoLista *elim = lista->inicio;
        if (index == 0) {
            lista->inicio = obtenerSiguiente_nodoLista(lista->inicio);
        } else {
            int i = 0;
            while (i < (index - 1)) {
                runner = obtenerSiguiente_nodoLista(runner);
                i++;
            }
            elim = obtenerSiguiente_nodoLista(runner);
            definirSiguiente_nodoLista(runner, obtenerSiguiente_nodoLista(obtenerSiguiente_nodoLista(runner)));
        }
        free(elim);
        lista->longitud = longitud_listaListas(lista) - 1;
    }
}

void borrar_listaListas(ListaListas *lista, int index) {
    reescribir_listaListas(lista, NULL, index);
}